package auto.app.service.impl;

import auto.app.controller.from.connectionConfigurationFrom.ConnectionConfigurationAdd;
import auto.app.controller.from.connectionConfigurationFrom.ConnectionConfigurationPageFrom;
import auto.app.controller.from.connectionConfigurationFrom.ConnectionConfigurationUpdate;
import auto.app.controller.info.ConnecitonInfo.ConnectionConfiguraDetailInfo;
import auto.app.controller.info.ConnecitonInfo.ConnectionConfiguraPageInfo;
import auto.app.exetion.MainExection;
import auto.app.model.ConnectionConfiguration;
import auto.app.dao.ConnectionConfigurationDao;
import auto.app.service.ConnectionConfigurationService;
import auto.app.util.CommonUtil;
import auto.app.util.ObjectNull;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.function.Consumer;

import static auto.app.exetion.MainExetionMessage.CONNECTIONNAMESAVE;
import static auto.app.exetion.MainExetionMessage.CONNECTIONSLECTERROR;

/**
 * <p>
 * 数据库管理 服务实现类
 * </p>
 *
 * @author 杨森
 * @since 2022-10-10
 */
@Service
@Slf4j
public class ConnectionConfigurationServiceImpl extends ServiceImpl<ConnectionConfigurationDao, ConnectionConfiguration> implements ConnectionConfigurationService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addConnectionConfiguration(ConnectionConfigurationAdd connectionConfigurationAdd) throws MainExection {
        LambdaQueryWrapper<ConnectionConfiguration>lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ConnectionConfiguration::getConnectionName,connectionConfigurationAdd.getConnectionName());
        ConnectionConfiguration connectionConfiguration = baseMapper.selectOne(lambdaQueryWrapper);
        if (ObjectUtil.isNotNull(connectionConfiguration)){
            throw new MainExection(CONNECTIONNAMESAVE.getCode(),CONNECTIONNAMESAVE.getMsg());
        }
        ConnectionConfiguration configuration = CommonUtil.copyOne(connectionConfigurationAdd, ConnectionConfiguration.class);
        configuration.setCreateTime(LocalDateTime.now());
        configuration.setConnectionDefault(0);
        int insert = baseMapper.insert(configuration);
        return insert > 0;
    }

    @Override
    public ConnectionConfiguraDetailInfo ConnectionConfigurationDetail(String connectionId) throws MainExection {
        ConnectionConfiguration configuration = baseMapper.selectById(connectionId);
        if (ObjectUtil.isNull(configuration)){
            throw new MainExection(CONNECTIONSLECTERROR.getCode(),CONNECTIONSLECTERROR.getMsg());
        }
        ConnectionConfiguraDetailInfo connectionConfiguraDetailInfo = CommonUtil.copyOne(configuration, ConnectionConfiguraDetailInfo.class);
        return connectionConfiguraDetailInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean connectionConfigurationUpdate(ConnectionConfigurationUpdate connectionConfigurationUpdate) throws MainExection {
        ConnectionConfiguration configuration = baseMapper.selectById(connectionConfigurationUpdate.getConnectionId());
        if (ObjectUtil.isNull(configuration)){
            throw new MainExection(CONNECTIONSLECTERROR.getCode(),CONNECTIONSLECTERROR.getMsg());
        }
        ConnectionConfiguration connectionConfiguration = CommonUtil.copyOne(connectionConfigurationUpdate, ConnectionConfiguration.class);
        connectionConfiguration.setUpdateTime(LocalDateTime.now());
        int update = baseMapper.updateById(connectionConfiguration);
        return update>0;
    }

    @Override
    public ConnectionConfiguraPageInfo connectionConfigurationList(ConnectionConfigurationPageFrom connectionConfigurationPageFrom) {
        LambdaQueryWrapper<ConnectionConfiguration>lambdaQueryWrapper=new LambdaQueryWrapper<>();
        //按类型查询
        lambdaQueryWrapper.eq(ObjectNull.isNotNull(connectionConfigurationPageFrom.getConnectionType()),ConnectionConfiguration::getConnectionType,connectionConfigurationPageFrom.getConnectionType())
                //按是否默认查询
                .eq(ObjectNull.isNotNull(connectionConfigurationPageFrom.getConnectionDefault()),ConnectionConfiguration::getConnectionDefault,connectionConfigurationPageFrom.getConnectionDefault())
                //按IP地址查询
                .eq(ObjectNull.isNotNull(connectionConfigurationPageFrom.getConnectionIp()),ConnectionConfiguration::getConnectionIp,connectionConfigurationPageFrom.getConnectionIp())
                //按连接名称查询
                .eq(ObjectNull.isNotNull(connectionConfigurationPageFrom.getConnectionName()),ConnectionConfiguration::getConnectionName,connectionConfigurationPageFrom.getConnectionName())
                //按创建时间倒序
                .orderByDesc(ConnectionConfiguration::getCreateTime);

        ConnectionConfigurationPageFrom configurationPageFrom = baseMapper.selectPage(connectionConfigurationPageFrom, lambdaQueryWrapper);
        return  CommonUtil.copyOne(configurationPageFrom, ConnectionConfiguraPageInfo.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean connectionConfigurationDel(String connectionId) throws MainExection {
        ConnectionConfiguration configuration = baseMapper.selectById(connectionId);
        if (ObjectUtil.isNull(configuration)){
            throw new MainExection(CONNECTIONSLECTERROR.getCode(),CONNECTIONSLECTERROR.getMsg());
        }
        //后面使用后需要判断是否正在使用
        int i = baseMapper.deleteById(connectionId);
        return i>0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean connectionConfigurationTest(String connectionId) throws MainExection, ClassNotFoundException {
        ConnectionConfiguration configuration = baseMapper.selectById(connectionId);
        if (ObjectUtil.isNull(configuration)){
            throw new MainExection(CONNECTIONSLECTERROR.getCode(),CONNECTIONSLECTERROR.getMsg());
        }
        Class.forName("com.mysql.jdbc.Driver");//加载驱动类
        String url="";
        //设置链接地址 端口 密码
        if (ObjectUtil.isNotNull(configuration.getConnectionPort())){
            url="jdbc:mysql://"+configuration.getConnectionIp()+":"+configuration.getConnectionPort()+"/"+configuration.getConnectionDatabase();
        }else{
            url="jdbc:mysql://"+configuration.getConnectionIp()+"/"+configuration.getConnectionDatabase();
        }
        String urlNew=url+"?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true&autoReconnect=true&serverTimezone=UTC";
        String username=configuration.getConnectionUsername();
        String password=configuration.getConnectionPassword();
        Connection conn= null;//用参数得到连接对象
        try {
            conn = DriverManager.getConnection(urlNew,username,password);
            log.info("连接成功");
            log.info(conn.toString());
            return true;
        } catch (SQLException e) {
            throw new MainExection(500,e.getMessage());
        }
    }

    @Override
    public Boolean defaultUpdateConfiguration(String connectionId) throws MainExection {
        ConnectionConfiguration configuration = baseMapper.selectById(connectionId);
        if (ObjectUtil.isNull(configuration)){
            throw new MainExection(CONNECTIONSLECTERROR.getCode(),CONNECTIONSLECTERROR.getMsg());
        }
        LambdaQueryWrapper<ConnectionConfiguration> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ConnectionConfiguration::getConnectionDefault,1);
        List<ConnectionConfiguration> list = list(lambdaQueryWrapper);
        if (ObjectUtil.isNotNull(list) && list.size()>0){
            list.forEach(connectionConfiguration -> connectionConfiguration.setConnectionDefault(0));
            boolean isUpdate= updateBatchById(list);
            if(isUpdate){
                configuration.setConnectionDefault(1);
                return updateById(configuration);
            }
        }else {
            configuration.setConnectionDefault(1);
            return updateById(configuration);
        }
        return false;
    }

}
